#include "SqlTableHelper.h"
#include "json.h"
#include "Util/logc.h"
namespace Media{

    bool toScenesInItemConfig(const scenesTable& sc, std::map<uint32_t,VideoScenesInItemConfig>& vMap,
        std::map<uint32_t, AudioScenesInItemConfig>& aMap){
        Json::Value jsonV;
        Json::Reader reader;

        std::vector<scenesItemTable> tbs;
        if(SqlTableOp::Instance()->GetAllTable<scenesItemTable>(tbs)){
            for(const auto& tb:tbs){
                VideoScenesInItemConfig vItem;
                AudioScenesInItemConfig aItem;
                
                tracef("scenesItemTable  m_itemDesc %s", tb.m_itemDesc.c_str());
                if(reader.parse(tb.m_itemDesc, jsonV)){
                    if(jsonV.isMember("x")){
                        vItem.m_x = jsonV["x"].asInt();
                    }
                    if(jsonV.isMember("y")){
                        vItem.m_y = jsonV["y"].asInt();
                    }
                    if(jsonV.isMember("width")){
                        vItem.m_width = jsonV["width"].asInt();
                    }
                    if(jsonV.isMember("height")){
                        vItem.m_height = jsonV["height"].asInt();
                    }
                    if(jsonV.isMember("layers")){
                        vItem.m_layers = jsonV["layers"].asInt();
                    }
                }
                
                inputSourceTable itb;
                if(SqlTableOp::Instance()->GetOneTable<inputSourceTable>(tb.m_sourceId, itb)){
                    vItem.m_sourceId = tb.m_sourceId;
                    vItem.m_content = itb.m_content;
                    aItem.m_sourceId = tb.m_sourceId;
                    aItem.m_content = itb.m_content;
                }else{
                    continue;
                }

                if(tb.m_type == MediaVideo){
                    vMap[tb.m_id] = vItem;
                }else if(tb.m_type == MediaAudio){
                    aMap[tb.m_id] = aItem;
                }else{
                    continue;
                }
            }
            return true;
        }
    
        return false;
    }

    bool toVideoScenesOutItemConfig(const scenesTable& sc, VideoScenesOutItemConfig& outConfig, std::vector<uint32_t>& sources){
        Json::Value jsonItems;
        Json::Reader reader;

        if(!sc.m_videoOutputConfig.empty() && !reader.parse(sc.m_videoOutputConfig, jsonItems)){
            return false;
        }

        int width = 1920;
        int height = 1080;
        int frameRate = 0;
        int bitRate = 0;
        std::string codec_name = "H264";

        //json array {"resolution":{"width":1920, "height":1080}, "frameRate":30, "bitRate":"4096", "codec":"H264", "outputList":[{"outputId":2}, {"outputId":3}]}
        if(jsonItems.isMember("resolution") && jsonItems["resolution"].isMember("width")
            && jsonItems["resolution"].isMember("height")){
                width = jsonItems["resolution"]["width"].asInt();
                height = jsonItems["resolution"]["height"].asInt();
        }

        if(jsonItems.isMember("frameRate")){
            frameRate = jsonItems["frameRate"].asInt();
        }
        if(jsonItems.isMember("bitRate")){
            bitRate = jsonItems["bitRate"].asInt();
        }
        if(jsonItems.isMember("codec")){
            codec_name = jsonItems["codec"].asString();
        }

        outConfig.m_bitRate = bitRate;
        outConfig.m_codec = codec_name;
        outConfig.m_frameRate = frameRate;
        outConfig.m_width = width;
        outConfig.m_height = height;

        if(jsonItems.isMember("outputList") && jsonItems["outputList"].isArray()){
            for(auto item:jsonItems["outputList"]){
                if(item.isMember("outputId")){
                    sources.push_back(item["outputId"].asUInt());
                }
            }
        }

        return true;
    }
    bool toAudioScenesOutItemConfig(const scenesTable& sc,AudioScenesOutItemConfig& outConfig, std::vector<uint32_t>& sources){
        Json::Value jsonItems;
        Json::Reader reader;
        if(!reader.parse(sc.m_audioOutputConfig, jsonItems)){
            return false;
        }

        //json array {"sampleRate":44100, "channel":2, "codec":"AAC","outputList":[{"outputId":4}, {"outputId":5}]}
        int sampleRate = 44100;
        int channel = 2;
        std::string codec_name = "AAC";

        if(jsonItems.isMember("sampleRate")){
            sampleRate = jsonItems["sampleRate"].asInt();
        }

        if(jsonItems.isMember("channel")){
            channel = jsonItems["channel"].asInt();
        }

        if(jsonItems.isMember("codec_name")){
            codec_name = jsonItems["codec_name"].asString();
        }

        if(!jsonItems.isMember("outputList") || !jsonItems["outputList"].isArray()){
            return false;
        }

        outConfig.m_channel = channel;
        outConfig.m_codec = codec_name;
        outConfig.m_sampleRate = sampleRate;

        for(auto item:jsonItems["outputList"]){
            if(item.isMember("outputId")){
                sources.push_back(item["outputId"].asUInt());
            }
        }

        return true;
    }


    bool toVideoItemTable(const VideoScenesInItemConfig& config, scenesItemTable& tb){
        tb.m_sourceId = config.m_sourceId;
        tb.m_type = MediaVideo;
        Json::Value desc;
        desc["x"] = config.m_x;
        desc["y"] = config.m_y;
        desc["width"] = config.m_width;
        desc["height"] = config.m_height;
        desc["layers"] = config.m_layers;
        tb.m_itemDesc = desc.toStyledString();
        return true;
    }
    bool toAudioItemTable(const AudioScenesInItemConfig& config, scenesItemTable& tb){
        tb.m_sourceId = config.m_sourceId;
        tb.m_type = MediaAudio;

        return true;
    }


    bool toVideoOutTableString(const VideoScenesOutItemConfig& outConfig, std::string& tableStr){
        //json array {"resolution":{"width":1920, "height":1080}, "frameRate":30, "bitRate":"4096", "codec":"H264", "outputList":[{"outputId":2}, {"outputId":3}]}
        Json::Value outJson;
        Json::Reader reader;

        if(!tableStr.empty() && !reader.parse(tableStr, outJson)){
            return false;
        }

        outJson["resolution"]["width"] = outConfig.m_width;
        outJson["resolution"]["height"] = outConfig.m_height;
        outJson["frameRate"] = outConfig.m_frameRate;
        outJson["bitRate"] = outConfig.m_bitRate;
        outJson["codec"] = outConfig.m_codec;

        tableStr = outJson.toStyledString();
        return true;
    }
    bool toAudioOutTableString(const AudioScenesOutItemConfig& outConfig, std::string& tableStr){
        //{"sampleRate":44100, "channel":2, "codec":"AAC","outputList":[{"outputId":4}, {"outputId":5}]}
        Json::Value outJson;
        Json::Reader reader;
        if(!reader.parse(tableStr, outJson)){
            return false;
        }
        outJson["sampleRate"] = outConfig.m_sampleRate;
        outJson["channel"] = outConfig.m_channel;
        outJson["codec"] = outConfig.m_codec;
        tableStr = outJson.toStyledString();
        return true;
    }
    

    bool toAddOutSourceTableString(uint32_t sourceId, std::string& tableStr){
        //json array {"resolution":{"width":1920, "height":1080}, "frameRate":30, "bitRate":"4096", "codec":"H264", "outputList":[{"outputId":2}, {"outputId":3}]}
        Json::Value outJson;
        Json::Reader reader;
        if(!reader.parse(tableStr, outJson)){
            return false;
        }
        Json::Value &list = outJson["outputList"];
        for(auto output:list){
            if(output.isMember("outputId") &&
                output["outputId"].asUInt() == sourceId){
                return false;
            }
        }
        Json::Value newSource;
        newSource["outputId"] = sourceId;
        list.append(newSource);
        tableStr = outJson.toStyledString();
        return true;
    }
    bool toRemoveOutSourceTableString(uint32_t sourceId, std::string& tableStr){
        Json::Value outJson;
        Json::Reader reader;
        if(!reader.parse(tableStr, outJson)){
            return false;
        }
        Json::Value &list = outJson["outputList"];
        Json::Value newList;
        for(auto output:list){
            if(output.isMember("outputId") && 
                output["outputId"].asUInt() != sourceId){
                newList.append(output);
            }
        }
        outJson["outputList"]=newList;
        tableStr = outJson.toStyledString();
        return true;
    }

}